home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / UnixFiles.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-19  |  13.9 KB  |  708 lines

  1. /*********************************************************************
  2. File        :    UnixFiles.h        -    Macintosh implementation of some things 
  3.                                         useful for handling UN*X files and such.
  4. Author    :    Matthias Neeracher <neeri@iis.ethz.ch>
  5. Started    :    28May91                                Language    :    MPW C
  6.                 28May91    MN    Created
  7.                 28May91    MN    isatty()
  8.                 09Dec91    MN    Radical overhaul
  9.                 12Dec91     MN FSp2RelPath
  10. Last        :    12Dec91
  11.  
  12. Copyright (c) 1991, 1992 Matthias Neeracher
  13.  
  14.     You may distribute under the terms of either the GNU General Public
  15.     License or the Artistic License, as specified in the README file.
  16.  
  17. *********************************************************************/
  18.  
  19. /* We need glue for Gestalt, but not for the rest of the stuff */
  20. #include <GestaltEqu.h>
  21.  
  22. #define SystemSevenOrLater    1
  23. #include "UnixFiles.h"
  24.  
  25. #include <Errors.h>
  26. #include <Memory.h>
  27. #include <string.h>
  28. #include <ioctl.h>
  29. #include <fcntl.h>
  30. #include <errno.h>
  31.  
  32. typedef enum {
  33.     dontKnow,
  34.     canRun,
  35.     cantRun
  36. } featureCheck;
  37.  
  38. /* Convert a working directory & file name into a FSSpec. */
  39. OSErr WD2FSSpec(short wd, Str63 name, FSSpec * desc)
  40. {
  41.     OSErr        err;
  42.     WDPBRec     wdPB;
  43.     
  44.     wdPB.ioNamePtr     = nil;
  45.     wdPB.ioVRefNum     = wd;
  46.     wdPB.ioWDIndex     = 0;
  47.     wdPB.ioWDProcID     = 0;
  48.     
  49.     /* Change the Working Directory number in vRefnum into a real vRefnum */
  50.     /* and DirID. The real vRefnum is returned in ioVRefnum, and the real */
  51.     /* DirID is returned in ioWDDirID. */
  52.     
  53.     if (err = PBGetWDInfoSync(&wdPB))
  54.         return err;
  55.     
  56.     desc->vRefNum    = wdPB.ioWDVRefNum;
  57.     desc->parID        = wdPB.ioWDDirID;
  58.     memcpy(desc->name, name, *name+1);
  59.     
  60.     return noErr;
  61. }
  62.  
  63. #define    maxPathLen 512
  64.  
  65. static char fullPath[maxPathLen];
  66.  
  67. /* Convert an FSSpec into a full pathname. The pathname is accumulated on the
  68.    high end of path to avoid excessive copying.
  69. */
  70.  
  71. char * FSp2FullPath(const FSSpec * desc)
  72. {
  73.     CInfoPBRec  block;
  74.     char *        curPath;
  75.     
  76.     /* Special case: a volume was specified */
  77.     if (desc->parID == fsRtParID)    {
  78.         memcpy(fullPath, desc->name+1, *desc->name);
  79.         curPath        =    fullPath+*desc->name;
  80.         curPath[0]    =    ':';
  81.         curPath[1]    =    0;
  82.         
  83.         return fullPath;
  84.     }
  85.         
  86.     fullPath[maxPathLen-1]    =    0;
  87.     curPath                         =    fullPath+maxPathLen-*desc->name-1;
  88.     
  89.     memcpy(curPath, desc->name+1, *desc->name);
  90.     
  91.    block.dirInfo.ioNamePtr = (StringPtr) fullPath;
  92.    block.dirInfo.ioDrParID = desc->parID;
  93.  
  94.    do {
  95.        block.dirInfo.ioVRefNum     = desc->vRefNum;
  96.        block.dirInfo.ioFDirIndex = -1;
  97.        block.dirInfo.ioDrDirID     = block.dirInfo.ioDrParID;
  98.  
  99.        PBGetCatInfoSync(&block);
  100.        *--curPath    =    ':';
  101.          curPath    -=    *fullPath;
  102.          memmove(curPath, fullPath+1, *fullPath);
  103.    } while (block.dirInfo.ioDrDirID != fsRtDirID);
  104.  
  105.     return curPath;
  106. }
  107.  
  108. char * FSp2RelPath(const FSSpec * desc)
  109. {
  110.     short            curVRef;
  111.     long            curDirID;
  112.     CInfoPBRec  block;
  113.     char *        curPath;
  114.     
  115.     {
  116.         WDPBRec    vol;
  117.         
  118.         vol.ioNamePtr    =    (StringPtr)fullPath;
  119.         
  120.         PBHGetVolSync(&vol);
  121.             
  122.         curVRef            =    vol.ioWDVRefNum;
  123.         curDirID            =    vol.ioWDDirID;
  124.     }
  125.     
  126.     /* Special case: a volume was specified */
  127.     if (desc->parID == fsRtParID)    {
  128.         if (desc->vRefNum == curVRef && curDirID == fsRtDirID)
  129.             curPath = fullPath;
  130.         else {
  131.             memcpy(fullPath, desc->name+1, *desc->name);
  132.             curPath        =    fullPath+*desc->name;
  133.         }
  134.         
  135.         curPath[0]    =    ':';
  136.         curPath[1]    =    0;
  137.         
  138.         return fullPath;
  139.     }
  140.  
  141.     block.dirInfo.ioNamePtr        =    (StringPtr)fullPath;
  142.     block.dirInfo.ioVRefNum     =     curVRef;
  143.     block.dirInfo.ioFDirIndex     =     -1;
  144.     block.dirInfo.ioDrDirID     =     curDirID;
  145.     
  146.     PBGetCatInfoSync(&block);
  147.     
  148.     if (curVRef == desc->vRefNum 
  149.         && block.dirInfo.ioDrParID == desc->parID
  150.         && !memcmp (fullPath, desc->name, *fullPath+1)
  151.     )    {
  152.         fullPath[0]    =    ':';
  153.         fullPath[1] =     0;
  154.         
  155.         return fullPath;
  156.     }
  157.         
  158.     fullPath[maxPathLen-1]    =    0;
  159.     curPath                         =    fullPath+maxPathLen-*desc->name-1;
  160.     
  161.     memcpy(curPath, desc->name+1, *desc->name);
  162.     
  163.    block.dirInfo.ioNamePtr = (StringPtr) fullPath;
  164.    block.dirInfo.ioDrParID = desc->parID;
  165.  
  166.    do {
  167.       *--curPath    =    ':';
  168.          
  169.         /* Test fur current directory */
  170.         if (curVRef == desc->vRefNum && curDirID == block.dirInfo.ioDrParID)
  171.             return strchr(curPath+1, ':') ? curPath : curPath+1;
  172.             
  173.         block.dirInfo.ioVRefNum     = desc->vRefNum;
  174.         block.dirInfo.ioFDirIndex = -1;
  175.         block.dirInfo.ioDrDirID     = block.dirInfo.ioDrParID;
  176.         
  177.         PBGetCatInfoSync(&block);
  178.         curPath    -=    *fullPath;
  179.         memmove(curPath, fullPath+1, *fullPath);
  180.    } while (block.dirInfo.ioDrDirID != fsRtDirID);
  181.  
  182.     return curPath;
  183. }    
  184.  
  185.  
  186. /* Call GetCatInfo for file system object. */
  187. OSErr    FSpCatInfo(const FSSpec * desc, CInfoPBRec * info)
  188. {
  189.    info->dirInfo.ioVRefNum     = desc->vRefNum;
  190.    info->dirInfo.ioDrDirID     = desc->parID;
  191.    info->dirInfo.ioNamePtr     = desc->name;
  192.    info->dirInfo.ioFDirIndex     = 0;
  193.  
  194.    return PBGetCatInfoSync(info);
  195. }
  196.  
  197. /* Is Object a file ? */
  198. Boolean IsFile(const CInfoPBRec * info)
  199. {
  200.     return !(info->dirInfo.ioFlAttrib & 0x10);
  201. }
  202.  
  203. /* Return FSSpec of (vRefNum, parID) */
  204. OSErr FSpUp(FSSpec * desc)
  205. {
  206.     OSErr            err;
  207.     CInfoPBRec  cb;
  208.     
  209.     if (desc->parID == fsRtParID)
  210.         return noErr;
  211.         
  212.    cb.dirInfo.ioVRefNum     = desc->vRefNum;
  213.    cb.dirInfo.ioDrDirID     = desc->parID;
  214.    cb.dirInfo.ioNamePtr     = desc->name;
  215.    cb.dirInfo.ioFDirIndex     = -1;
  216.  
  217.    if (err = PBGetCatInfoSync(&cb))
  218.         return err;
  219.     
  220.     desc->parID    = (desc->parID == fsRtDirID) ? fsRtParID : cb.dirInfo.ioDrParID;
  221.     
  222.     return noErr;
  223. }
  224.  
  225. /* Return FSSpec of file in directory denoted by desc */
  226. OSErr FSpDown(FSSpec * desc, ConstStr31Param name)
  227. {
  228.     OSErr            err;
  229.     CInfoPBRec  cb;
  230.     
  231.    if (err = FSpCatInfo(desc, &cb))
  232.         return err;
  233.     if (IsFile(&cb))
  234.         return bdNamErr;
  235.     
  236.     desc->parID    = cb.dirInfo.ioDrDirID;
  237.  
  238.     memcpy(desc->name, name, *name+1);
  239.     
  240.     return noErr;
  241. }
  242.  
  243. /* Return FSSpec of nth file in directory denoted by (vRefNum, parID) */
  244. OSErr FSpIndex(FSSpec * desc, short n)
  245. {
  246.     CInfoPBRec  cb;
  247.     
  248.    cb.dirInfo.ioVRefNum     = desc->vRefNum;
  249.    cb.dirInfo.ioDrDirID         = desc->parID;
  250.    cb.dirInfo.ioNamePtr     = desc->name;
  251.    cb.dirInfo.ioFDirIndex     = n;
  252.  
  253.    return PBGetCatInfoSync(&cb);
  254. }
  255.  
  256. /* A version of PBGetCatInfo for c strings that may be longer than 255 chars
  257. */
  258.  
  259. static OSErr    GetCatInfo(char * path, CInfoPBPtr cb)
  260. {
  261.     char    *            nextPath;
  262.     char    *          tryPath;
  263.     OSErr                err;
  264.     StringPtr        name    =    (StringPtr) fullPath;
  265.  
  266.     if (*path != ':' && (nextPath = strchr(path, ':')))    {
  267.         ParamBlockRec    vol;
  268.         
  269.         memcpy(name+1, path, *name = nextPath-path+1);
  270.         
  271.         vol.volumeParam.ioNamePtr     = name;
  272.         vol.volumeParam.ioVolIndex    = -1;
  273.  
  274.         if (err = PBGetVInfoSync(&vol))
  275.             return err;
  276.             
  277.         cb->dirInfo.ioVRefNum    =    vol.volumeParam.ioVRefNum;
  278.         cb->dirInfo.ioDrDirID    =    fsRtDirID;
  279.         
  280.         path    = nextPath;
  281.     } else {
  282.         WDPBRec    vol;
  283.         
  284.         vol.ioNamePtr    =    name;
  285.         
  286.         if (err = PBHGetVolSync(&vol))
  287.             return err;
  288.             
  289.         cb->dirInfo.ioVRefNum    =    vol.ioWDVRefNum;
  290.         cb->dirInfo.ioDrDirID    =    vol.ioWDDirID;
  291.     }
  292.     
  293.     cb->dirInfo.ioNamePtr    =    name;
  294.     cb->dirInfo.ioFDirIndex    =    0;
  295.  
  296.     /* handle very long pathnames */
  297.  
  298.     while (strlen(path) > 255)    {
  299.         for (nextPath    =    path; tryPath = strchr(nextPath, ':'); nextPath = tryPath)
  300.             if (tryPath-nextPath > 31)
  301.                 return bdNamErr;
  302.             else if (tryPath-path > 255)
  303.                 break;
  304.  
  305.         if (nextPath == path && !tryPath)
  306.             return bdNamErr;
  307.  
  308.         memcpy(name+1, path, name[0] = nextPath-path);
  309.  
  310.         if (err = PBGetCatInfoSync(cb))
  311.             return err;
  312.  
  313.         if (IsFile(cb))
  314.             return bdNamErr;
  315.  
  316.         cb->dirInfo.ioFDirIndex    =    0;
  317.  
  318.         path    =    nextPath+1;
  319.     }
  320.     
  321.     memcpy(name+1, path, name[0] = strlen(path));
  322.  
  323.     if (err = PBGetCatInfoSync(cb))
  324.         return err;
  325.     
  326.     if (!IsFile(cb))    {
  327.         cb->dirInfo.ioFDirIndex    = -1;
  328.         
  329.         return PBGetCatInfoSync(cb);
  330.     } else {
  331.         while (fullPath[*fullPath] == ':')
  332.             fullPath[(*fullPath)--]    =    0;
  333.         
  334.         if (path = strrchr(fullPath+1, ':'))
  335.             memcpy(fullPath+1, path+1, *fullPath = path-fullPath);
  336.         
  337.         return noErr;
  338.     }
  339. }
  340.  
  341. OSErr Path2FSSpec(char * path, FSSpec * desc)
  342. {
  343.     static featureCheck    hasFSMakeFSSpec    =    dontKnow;
  344.  
  345.     int    pathLen    = strlen(path);
  346.     
  347.     if (hasFSMakeFSSpec == dontKnow) {
  348.         long        attr;
  349.         
  350.         if (!Gestalt(gestaltFSAttr, &attr) && (attr & gestaltHasFSSpecCalls))
  351.             hasFSMakeFSSpec    =    canRun;
  352.         else
  353.             hasFSMakeFSSpec    =    cantRun;
  354.     }
  355.     
  356.     if (hasFSMakeFSSpec == canRun && pathLen<256)    {
  357.         Str255     pathName;
  358.         
  359.         memcpy(pathName+1, path, pathLen);
  360.         
  361.         *pathName    =    pathLen;
  362.         
  363.         return FSMakeFSSpec(0, 0, pathName, desc);
  364.     } else {
  365.         OSErr            err;
  366.         CInfoPBRec  cb;
  367.         
  368.         if (err = GetCatInfo(path, &cb))
  369.             return err;
  370.         
  371.         desc->vRefNum    =    cb.hFileInfo.ioVRefNum;
  372.         desc->parID        =    cb.hFileInfo.ioFlParID;
  373.         
  374.         memcpy(desc->name, fullPath, *fullPath+1);
  375.     }
  376.     
  377.     return noErr;
  378. }
  379.  
  380. static OSErr    GetFDCatInfo(int fd, CInfoPBPtr cb)
  381. {
  382.     short                fRef;
  383.     OSErr                err;
  384.     FCBPBRec            fcb;
  385.     Str255            fname;
  386.  
  387.     if (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1)
  388.         return fnfErr;
  389.  
  390.     fcb.ioNamePtr    =     fname;
  391.     fcb.ioRefNum    =    fRef;
  392.     fcb.ioFCBIndx    =     0;
  393.     if (err = PBGetFCBInfoSync(&fcb))
  394.         return err;
  395.  
  396.     cb->hFileInfo.ioNamePtr        =    fname;
  397.     cb->hFileInfo.ioDirID        =    fcb.ioFCBParID;
  398.     cb->hFileInfo.ioVRefNum        =    fcb.ioFCBVRefNum;
  399.     cb->hFileInfo.ioFDirIndex    =    0;
  400.  
  401.     return PBGetCatInfoSync(cb);
  402. }
  403.  
  404. static OSErr GetVolume(CInfoPBPtr cb, ParmBlkPtr pb)
  405. {
  406.     Str63                name;
  407.  
  408.     pb->volumeParam.ioNamePtr    =    name;
  409.     pb->volumeParam.ioVRefNum    =    cb->hFileInfo.ioVRefNum;
  410.     pb->volumeParam.ioVolIndex    =    0;
  411.  
  412.     return PBGetVInfo(pb, false);
  413. }
  414.  
  415. static int do_stat(CInfoPBPtr cb, ParmBlkPtr pb, struct stat * buf)
  416. {
  417.     buf->st_dev        =    pb->ioParam.ioVRefNum;
  418.     buf->st_ino        =    cb->hFileInfo.ioDirID;
  419.     buf->st_nlink    =    1;
  420.     buf->st_uid        =    0;
  421.     buf->st_gid        =    0;
  422.     buf->st_rdev    =    0;
  423.     buf->st_atime    =    cb->hFileInfo.ioFlMdDat;
  424.     buf->st_mtime    =    cb->hFileInfo.ioFlMdDat;
  425.     buf->st_ctime    =    cb->hFileInfo.ioFlCrDat;
  426.     buf->st_blksize=    pb->volumeParam.ioVAlBlkSiz;
  427.  
  428.     if (!IsFile(cb))    {
  429.         buf->st_mode    =    S_IFDIR | 0777;
  430.         buf->st_size    =    buf->st_blksize;    /* Not known for directories    */
  431.     } else {
  432.         buf->st_mode    =    S_IFREG | 0666;
  433.  
  434.         if (cb->hFileInfo.ioFlAttrib & 0x01)
  435.             buf->st_mode&=    0222;
  436.  
  437.         if (cb->hFileInfo.ioFlFndrInfo.fdType == 'APPL')
  438.             buf->st_mode|=    0111;
  439.  
  440.         buf->st_size    =    cb->hFileInfo.ioFlLgLen;        /* Resource fork is ignored    */
  441.     }
  442.  
  443.     buf->st_blocks    =    (buf->st_size + buf->st_blksize - 1) / buf->st_blksize;
  444.  
  445.     return 0;
  446. }
  447.  
  448. int    stat(char * path, struct stat * buf)
  449. {
  450.     CInfoPBRec        cb;
  451.     ParamBlockRec    pb;
  452.  
  453.     if (GetCatInfo(path, &cb) || GetVolume(&cb, &pb)) {
  454.         errno = ENOENT;
  455.  
  456.         return -1;
  457.     } else
  458.         return do_stat(&cb, &pb, buf);
  459. }
  460.  
  461. /* Not yet really implemented */
  462.  
  463. int    lstat(char * path, struct stat * buf)
  464. {
  465.     return stat(path, buf);
  466. }
  467.  
  468. int    fstat(int fd, struct stat * buf)
  469. {
  470.     CInfoPBRec        cb;
  471.     ParamBlockRec    pb;
  472.  
  473.     if (GetFDCatInfo(fd, &cb))
  474.         if (lseek(fd, (long) 0, SEEK_CUR) != -1)    {
  475.             /* lseek() works, assume that this is a pseudo file (e.g. Dev:Null) 
  476.                 (Provided by Tim Endres <time@ice.com>)
  477.             */
  478.             buf->st_dev            =    0;
  479.             buf->st_ino            =    0;
  480.             buf->st_mode        =    S_IFCHR | 0777;
  481.             buf->st_nlink        =    1;
  482.             buf->st_uid            =    0;
  483.             buf->st_gid            =    0;
  484.             buf->st_rdev        =    0;
  485.             buf->st_size        =    1;
  486.             buf->st_atime        =    time(NULL);
  487.             buf->st_mtime        =    time(NULL);
  488.             buf->st_ctime        =    time(NULL);
  489.             buf->st_blksize    =    1;
  490.             buf->st_blocks        =    1;
  491.     
  492.             return 0;
  493.         } else {
  494.             errno = ENOENT;
  495.     
  496.             return -1;
  497.         }
  498.     else if (GetVolume(&cb, &pb)) {
  499.         errno = ENOENT;
  500.  
  501.         return -1;
  502.     } else
  503.         return do_stat(&cb, &pb, buf);
  504. }
  505.  
  506. int isatty(int fd)
  507. {
  508.     short    fRef;
  509.     
  510.     /* Another application of Tim Endres' idea. Neat, huh ? */
  511.     
  512.     return     (ioctl(fd, FIOREFNUM, (long *) &fRef) == -1) &&
  513.                 (lseek(fd, (long) 0, SEEK_CUR) != -1);
  514. }
  515.  
  516. struct dir {
  517.     short            index;
  518.     short            vol;
  519.     long            dirID;
  520.     direct        entry;
  521. };
  522.  
  523. DIR * opendir(char * name)
  524. {
  525.     DIR *            d;
  526.     CInfoPBRec    direct;
  527.     
  528.     d = (DIR *) NewPtr(sizeof(DIR));
  529.     
  530.     if (!d)
  531.         return nil;
  532.     else if (GetCatInfo(name, &direct) || IsFile(&direct))    {
  533.         DisposPtr((Ptr) d);
  534.         return nil;
  535.     }
  536.     
  537.     d->index    =    1;
  538.     d->vol    =    direct.dirInfo.ioVRefNum;
  539.     d->dirID    =    direct.dirInfo.ioDrDirID;
  540.     
  541.     return d;
  542. }
  543.     
  544. direct *    readdir(DIR * dirp)
  545. {
  546.     CInfoPBRec    info;
  547.     
  548.     dirp->entry.d_namelen        =    0;
  549.     info.hFileInfo.ioNamePtr    =    (StringPtr) dirp->entry.d_name-1;
  550.     info.hFileInfo.ioVRefNum    =    dirp->vol;
  551.     info.hFileInfo.ioFDirIndex    =    dirp->index;
  552.     info.hFileInfo.ioDirID        =    dirp->dirID;
  553.     
  554.     if (PBGetCatInfo(&info, false))
  555.         return nil;
  556.         
  557.     dirp->entry.d_name[dirp->entry.d_namelen] = 0;
  558.     dirp->index++;
  559.     
  560.     return &dirp->entry;
  561. }
  562.  
  563. long telldir(DIR * dirp)
  564. {
  565.     return dirp->index;
  566. }
  567.  
  568. void seekdir(DIR * dirp, long loc)
  569. {
  570.     dirp->index    =    loc;
  571. }
  572.  
  573. void rewinddir(DIR * dirp)
  574. {
  575.     dirp->index    =    1;
  576. }
  577.  
  578. void closedir(DIR * dirp)
  579. {
  580.     DisposPtr((Ptr) dirp);
  581. }
  582.  
  583. int chdir(char * path)    
  584. {
  585.     short            vRef;
  586.     CInfoPBRec    cb;
  587.     
  588.     if (GetCatInfo(path, &cb) ||╩IsFile(&cb)) {
  589.         errno = ENOENT;
  590.  
  591.         return -1;
  592.     } 
  593.     
  594.     /* HSetVol is too dangerous, create WD if necessary */
  595.     if (cb.dirInfo.ioDrDirID != fsRtDirID)
  596.         OpenWD(cb.dirInfo.ioVRefNum, cb.dirInfo.ioDrDirID, 'ERIK', &vRef);
  597.     else
  598.         vRef    =    cb.dirInfo.ioVRefNum;
  599.     
  600.     SetVol(nil, vRef);
  601.     
  602.     return 0;
  603. }
  604.  
  605. int mkdir(char * path)    
  606. {
  607.     OSErr            err;
  608.     short            vRef;
  609.     long            dirID;
  610.     long            nuDir;
  611.     int            len;
  612.     char *        dirPart;
  613.     Str31            name;
  614.     
  615.     if (dirPart = strrchr(path, ':')) {
  616.         char            saveCh;
  617.         CInfoPBRec    cb;
  618.         
  619.         saveCh         =     dirPart[1];
  620.         dirPart[1]    =    0;
  621.         err            =    GetCatInfo(path, &cb);
  622.         dirPart[1]  =    saveCh;
  623.         
  624.         if (err ||╩IsFile(&cb))    {
  625.             errno = ENOENT;
  626.  
  627.             return -1;
  628.         }
  629.         
  630.         if ((len = strlen(dirPart+1)) > 31)
  631.             return bdNamErr;
  632.         
  633.         memcpy(name+1, dirPart+1, *name = len);
  634.         
  635.         vRef    =    cb.dirInfo.ioVRefNum;
  636.         dirID    =    cb.dirInfo.ioDrDirID;
  637.     } else {
  638.         WDPBRec    vol;
  639.         
  640.         vol.ioNamePtr    =    name;
  641.         
  642.         if (err = PBHGetVolSync(&vol))
  643.             return err;
  644.             
  645.         if ((len = strlen(path)) > 31)
  646.             return bdNamErr;
  647.         
  648.         memcpy(name+1, path, *name = len);
  649.  
  650.         vRef    =    vol.ioWDVRefNum;
  651.         dirID    =    vol.ioWDDirID;
  652.     }
  653.     
  654.     if (err = DirCreate(vRef, dirID, name, &nuDir))    {
  655.         switch (err)    {
  656.         case bdNamErr:
  657.         case dirNFErr:
  658.         default:
  659.             errno    = ENOENT;
  660.             break;
  661.         case dupFNErr:
  662.             errno = EEXIST;
  663.             break;
  664.         case dirFulErr:
  665.             errno = ENOSPC;
  666.             break;
  667.         }
  668.         
  669.         return -1;
  670.     }
  671.  
  672.     return 0;
  673. }
  674.  
  675. int rmdir(char * path)    
  676. {
  677.     OSErr            err;
  678.     CInfoPBRec    cb;
  679.     
  680.     if (GetCatInfo(path, &cb) ||╩IsFile(&cb)) {
  681.         errno = ENOENT;
  682.  
  683.         return -1;
  684.     } 
  685.     
  686.     if (err = HDelete(cb.dirInfo.ioVRefNum, cb.dirInfo.ioDrDirID, "")) {
  687.         switch (err)    {
  688.         case bdNamErr:
  689.         case dirNFErr:
  690.         default:
  691.             errno    = ENOENT;
  692.             break;
  693.         case dupFNErr:
  694.         case fBsyErr:
  695.             errno = EEXIST;
  696.             break;
  697.         case dirFulErr:
  698.             errno = ENOSPC;
  699.             break;
  700.         }
  701.         
  702.         return -1;
  703.     }
  704.     
  705.     return 0;
  706. }
  707.  
  708.